import { Request, Response } from 'express';
import { AuthRequest } from '@/types';
import ApiResponse from '@/utils/api/api-response.util';
import { getLogger } from '@/utils/logger';
import * as si from 'systeminformation';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as os from 'os';
import { monitorEvents } from '@/services/monitor/metric.service';

const execAsync = promisify(exec);
const consoleLogger = getLogger('server-controller');
const logger = getLogger('server-controller', {
  console: false,
});

interface ServerInfoData {
  cpu: any;
  memory: any;
  os: any;
  disk: any;
  network: any;
  process: any;
  uptime: number;
}

/**
 * 服务器监控控制器
 */
class ServerController {
  /**
   * 获取服务器基本信息
   * @param req 请求对象
   * @param res 响应对象
   */
  async getServerInfo(req: AuthRequest, res: Response) {
    try {
      // 请求日志
      consoleLogger.info("获取服务器基本信息请求", {
        operator: req.user?.userName || 'unknown',
      });
      
      // 收集CPU信息
      const [
        cpuInfo, 
        currentLoad, 
        memInfo, 
        osInfo, 
        fsSize, 
        networkStats,
        processes,
        currentProcess
      ] = await Promise.all([
        si.cpu(),
        si.currentLoad(),
        si.mem(),
        si.osInfo(),
        si.fsSize(),
        si.networkStats(),
        si.processes(),
        si.processes().then(data => {
          const currentProcList = data.list.filter(proc => proc.pid === process.pid);
          return { list: currentProcList };
        })
      ]);
      
      // 构建服务器信息对象
      const serverInfo: ServerInfoData = {
        cpu: {
          model: cpuInfo.manufacturer + ' ' + cpuInfo.brand,
          cores: cpuInfo.cores,
          speed: cpuInfo.speed,
          usage: parseFloat(currentLoad.currentLoad.toFixed(2)),
          temperature: await this.getCpuTemperature()
        },
        memory: {
          total: memInfo.total,
          used: memInfo.used,
          free: memInfo.free,
          usage: parseFloat(((memInfo.used / memInfo.total) * 100).toFixed(2))
        },
        os: {
          platform: osInfo.platform,
          distro: osInfo.distro,
          release: osInfo.release,
          hostname: osInfo.hostname,
          uptime: os.uptime()
        },
        disk: fsSize.map(fs => ({
          fs: fs.fs,
          mount: fs.mount,
          size: fs.size,
          used: fs.used,
          usage: parseFloat((fs.use).toFixed(2))
        })),
        network: networkStats.map(net => ({
          interface: net.iface,
          rx: net.rx_bytes,
          tx: net.tx_bytes,
          rx_sec: net.rx_sec,
          tx_sec: net.tx_sec
        })),
        process: {
          total: processes.all,
          running: processes.running,
          current: {
            pid: process.pid,
            memory: currentProcess.list[0]?.mem || 0,
            cpu: currentProcess.list[0]?.cpu || 0
          }
        },
        uptime: process.uptime()
      };
      
      // 结果日志
      logger.info("获取服务器基本信息成功", {
        response: {
          cpu: {
            cores: serverInfo.cpu.cores,
            usage: serverInfo.cpu.usage,
          },
          memory: {
            usage: serverInfo.memory.usage,
          },
          os: {
            platform: serverInfo.os.platform,
            distro: serverInfo.os.distro,
          },
          diskCount: serverInfo.disk.length,
          networkCount: serverInfo.network.length,
        },
        operator: req.user?.userName || 'unknown',
      });
      
      ApiResponse.success(res, serverInfo);
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`获取服务器信息失败: ${error instanceof Error ? error.message : String(error)}`, {
        operator: req.user?.userName || 'unknown',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '获取服务器信息失败');
      }
    }
  }
  
  /**
   * 获取CPU温度信息（如果可用）
   * @returns CPU温度或null
   */
  private async getCpuTemperature(): Promise<number | null> {
    try {
      // 使用systeminformation获取温度
      const tempData = await si.cpuTemperature();
      if (tempData && tempData.main) {
        return tempData.main;
      }
      
      // 如果systeminformation不支持，尝试其他方法
      if (process.platform === 'linux') {
        const { stdout } = await execAsync('cat /sys/class/thermal/thermal_zone0/temp');
        const temp = parseInt(stdout.trim(), 10) / 1000;
        return !isNaN(temp) ? temp : null;
      }
      
      return null;
    } catch (error) {
      logger.debug('获取CPU温度失败:', error);
      return null;
    }
  }

  /**
   * 兼容 /monitor/server 路由，返回与 Java/前端一致的服务器监控结构
   * @param req 请求对象
   * @param res 响应对象
   */
  public async getServerMonitor(req: Request, res: Response) {
    try {
      // 请求日志
      consoleLogger.info("获取服务监控信息请求", {
        operator: req.user?.userName || 'unknown',
      });
      
      // 获取基础信息
      const [cpuInfo, currentLoad, memInfo, osInfo, fsSize] = await Promise.all([
        si.cpu(),
        si.currentLoad(),
        si.mem(),
        si.osInfo(),
        si.fsSize()
      ]);
      // CPU
      const cpu = {
        cpuNum: cpuInfo.cores,
        used: parseFloat(currentLoad.currentLoadUser.toFixed(2)),
        sys: parseFloat(currentLoad.currentLoadSystem.toFixed(2)),
        free: parseFloat((100 - currentLoad.currentLoad).toFixed(2))
      };
      // 内存（单位G，保留2位小数）
      const memTotal = (memInfo.total / 1024 / 1024 / 1024).toFixed(2);
      const memUsed = (memInfo.used / 1024 / 1024 / 1024).toFixed(2);
      const memFree = (memInfo.free / 1024 / 1024 / 1024).toFixed(2);
      const memUsage = ((memInfo.used / memInfo.total) * 100).toFixed(2);
      const mem = {
        total: memTotal,
        used: memUsed,
        free: memFree,
        usage: memUsage
      };
      // JVM（Node无JVM，兼容前端结构，部分字段可置空或模拟）
      const jvm = {
        name: 'Node.js',
        version: process.version,
        total: '',
        used: '',
        free: '',
        usage: '',
        startTime: '',
        runTime: '',
        home: process.execPath,
        inputArgs: process.argv.join(' ')
      };
      // 系统信息
      const sys = {
        computerName: osInfo.hostname,
        computerIp: '', // 可通过网络接口获取
        osName: osInfo.distro,
        osArch: osInfo.arch,
        userDir: process.cwd()
      };
      // 获取主机IP
      const interfaces = os.networkInterfaces();
      for (const name of Object.keys(interfaces)) {
        for (const iface of interfaces[name] || []) {
          if (iface.family === 'IPv4' && !iface.internal) {
            sys.computerIp = iface.address;
            break;
          }
        }
        if (sys.computerIp) break;
      }
      // 磁盘信息
      const sysFiles = fsSize.map(fs => ({
        dirName: fs.mount,
        sysTypeName: fs.type,
        typeName: fs.fs,
        total: (fs.size / 1024 / 1024 / 1024).toFixed(2) + 'G',
        free: (fs.available / 1024 / 1024 / 1024).toFixed(2) + 'G',
        used: (fs.used / 1024 / 1024 / 1024).toFixed(2) + 'G',
        usage: fs.use
      }));
      const data = { cpu, mem, jvm, sys, sysFiles };
      
      // 结果日志
      logger.info("获取服务监控信息成功", {
        response: {
          cpu: {
            cpuNum: cpu.cpuNum,
            used: cpu.used,
          },
          mem: {
            total: mem.total,
            usage: mem.usage,
          },
          sys: {
            computerName: sys.computerName,
            osName: sys.osName,
          },
          sysFilesCount: sysFiles.length,
        },
        operator: req.user?.userName || 'unknown',
      });
      
      ApiResponse.success(res, data);
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`获取服务监控信息失败: ${error instanceof Error ? error.message : String(error)}`, {
        operator: req.user?.userName || 'unknown',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '获取服务监控信息失败');
      }
    }
  }

  /**
   * 测试发送告警邮件
   * @param req 请求对象
   * @param res 响应对象
   */
  async testAlert(req: AuthRequest, res: Response) {
    try {
      const { type } = req.query;
      const operator = req.user?.userName || 'admin';
      
      // 请求日志
      consoleLogger.info("测试告警功能请求", {  
        query: req.query,
        body: req.body,
        type,
        operator,
      });
      
      // 发送测试告警事件
      monitorEvents.emit('alert', {
        type: 'test',
        message: '这是一条测试告警消息',
        data: {
          test: true,
          time: new Date().toISOString()
        },
        timestamp: Date.now()
      });
      
      // 结果日志
      logger.info("触发测试告警成功", {
        response: {
          query: req.query,
          body: req.body,
          type,
        },
        operator,
      });
      
      ApiResponse.success(res, null, '测试告警已触发，请检查邮箱');
    } catch (error) {
      // 详细的错误日志
      consoleLogger.error(`测试告警功能失败: ${error instanceof Error ? error.message : String(error)}`, {
        requestData: {
          body: req.body,
          query: req.query,
        },
        operator: req.user?.userName || 'unknown',
        stack: error instanceof Error ? error.stack : undefined
      });
      if (!res.headersSent) {
        ApiResponse.error(res, '测试告警功能失败');
      }
    }
  }
}

export default new ServerController(); 